package com.demo.official.order.producer;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author huangweiyue
 * @description 启动consumer 启动producer 观察控制台输出
 * 【全局有序】当发送和消费参与的Queue只有1个时所保证的有序是整个Topic中消息的顺序。
 * 在创建Topic时指定Queue的数量。有三种指定方式：
 * 1）在代码中创建Producer时，可以指定其自动创建的Topic的Queue数量
 * producer.setDefaultTopicQueueNums(1) 需要注意得是与对应的topic绑定，如果已经用topic默认创建了4个队列 再去设置1个队列 无效
 * 2）在RocketMQ可视化控制台中手动创建Topic时指定Queue数量
 * 3）使用mqadmin命令手动创建Topic时指定Queue数量
 * 本示例需要修改topic为order_topic1，搭配producer.setDefaultTopicQueueNums(1)一起使用
 * 【分区有序】
 * 一般性的选择算法是，让选择key（或其hash值）与该Topic所包含的Queue的数量取模，其结果
 * 即为选择出的Queue的QueueId
 * 本示例需要修改topic为order_topic
 * @date Created in 2021-09-12
 */
public class OrderProducer {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("order_producer_group_name");


        producer.setNamesrvAddr("127.0.0.1:9876");
        //order_topic1 设置1个队列 注意consumer输出的队列下标是0，order_topic是默认的4个队列
        //producer.setDefaultTopicQueueNums(1);
        producer.start();

        String[] tags = new String[]{"TagA", "TagC", "TagD"};

        // 订单列表
        List<OrderStep> orderList = OrderProducer.buildOrders();

        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = sdf.format(date);
        for (int i = 0; i < orderList.size(); i++) {
            // 加个时间前缀
            String body = dateStr + " Hello RocketMQ " + orderList.get(i);
            Message msg = new Message("order_topic", tags[i % tags.length], "KEY" + i, body.getBytes());

            SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
                //构造函数可以指定queue的，MessageQueue(String topic, String brokerName, int queueId)
                @Override
                public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                    Long id = (Long) arg;  //根据订单id选择发送queue
                    long index = id % mqs.size();
                    return mqs.get((int) index);
                }
            }, orderList.get(i).getOrderId());//订单id

            System.out.println(String.format("SendResult status:%s, queueId:%d, body:%s",
                    sendResult.getSendStatus(),
                    sendResult.getMessageQueue().getQueueId(),
                    body));
        }

        producer.shutdown();
    }

    /**
     * 生成模拟订单数据
     */
    private static List<OrderStep> buildOrders() {
        List<OrderStep> orderList = new ArrayList<OrderStep>();

        OrderStep orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111039L);
        orderDemo.setDesc("创建");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111065L);
        orderDemo.setDesc("创建");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111039L);
        orderDemo.setDesc("付款");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103117235L);
        orderDemo.setDesc("创建");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111065L);
        orderDemo.setDesc("付款");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103117235L);
        orderDemo.setDesc("付款");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111065L);
        orderDemo.setDesc("完成");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111039L);
        orderDemo.setDesc("推送");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103117235L);
        orderDemo.setDesc("完成");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111039L);
        orderDemo.setDesc("完成");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(10000000000L);
        orderDemo.setDesc("新增");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(10000000000L);
        orderDemo.setDesc("修改");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(10000000000L);
        orderDemo.setDesc("删除");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(10000000000L);
        orderDemo.setDesc("第二次新增");
        orderList.add(orderDemo);

        return orderList;
    }

    /**
     * 订单的步骤
     */
    private static class OrderStep {
        private long orderId;
        private String desc;

        public long getOrderId() {
            return orderId;
        }

        public void setOrderId(long orderId) {
            this.orderId = orderId;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        public String toString() {
            return "OrderStep{" +
                    "orderId=" + orderId +
                    ", desc='" + desc + '\'' +
                    '}';
        }
    }
}
